home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
JCSM Shareware Collection 1993 November
/
JCSM Shareware Collection - 1993-11.iso
/
cl720
/
sst115j.lzh
/
SSTMNU.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-07-17
|
11KB
|
371 lines
/* ------------------------------------------------------------------------ */
/* sstmenu.c */
/* pull-down menu interface routines */
/* */
/* CopyRight (C) 1991,1992 Steven Lutrov. All rights reserved. */
/* ------------------------------------------------------------------------ */
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <dos.h>
#include "sstvid.h"
#include "sstkey.h"
#include "sstwin.h"
#include "sstmnu.h"
typedef struct {
int x;
int xx;
} itemrec;
typedef struct _mstyle {
char *title; /* title string */
int tjust; /* title justification */
int border; /* border type */
int colour[4]; /* colours for window */
int hspace; /* spaces between horiz items */
int lspace; /* left margin */
int rspace; /* right marigin */
int hfull; /* use full horiz width */
} MSTYLE;
static MSTYLE ms = { /* set default to monochrome attributes */
"", JUST_C, BRD_SINGLE,
{ CLR(BLACK, LIGHTGRAY, DIM),
CLR(BLACK, LIGHTGRAY, DIM),
CLR(LIGHTGRAY, BLACK, BRIGHT),
CLR(BLACK, LIGHTGRAY, DIM)
},
2, /* spaces */
1, /* left margin */
1, /* right margin */
0 /* full screen width */
};
#define MWIN_BORDER (ms.colour[WIN_BORDER])
#define MWIN_TITLEC (ms.colour[WIN_TITLE])
#define MWIN_ACCENT (ms.colour[WIN_ACCENT])
#define MWIN_FACE (ms.colour[WIN_FACE])
#define MCOLOUR (ms.colour)
#define MAXITEMS 16 /* maximum horiz menu items */
#define HKTAG '~'
int msave = 1;
/* ------------------------------------------------------------------------ */
/* local function prototypes */
/* ------------------------------------------------------------------------ */
WINDOW *openmenu (MENU *mn, int hsel);
static int gethmenu (MENU *mn, WINDOW *hmenu, int hsel);
static int getvmn (MENU *mn, WINDOW *hmenu, int *, int );
static int haccent (MENU *mn, WINDOW *hmenu, int hsel, int vsel);
static void dimension (char *sl[], int *ht, int *wd);
static void light (MENU *mn, WINDOW *hmenu, int hsel, int d);
static int getwidth (MENU *mn);
static int getvertpos (char **sl, int h);
static void putitems (WINDOW *wnd, MENU *mn);
/* ------------------------------------------------------------------------ */
/* local variables */
/* ------------------------------------------------------------------------ */
static itemrec irec[MAXITEMS]; /* item records */
static int w; /* horizontal window width */
static int hc; /* horizontal item count */
/* ------------------------------------------------------------------------ */
/* display & process a menu */
/* ------------------------------------------------------------------------ */
int Mselect(MENU *mn, int h)
{
WINDOW *openmenu();
WINDOW *hmenu;
int hsel = 1, vsel;
vpushcur();
vhidecur();
if ((w = getwidth(mn)) > SCREENWIDTH)
return (-1);
w = ((ms.hfull) ? SCREENWIDTH : w);
if ((hmenu = openmenu(mn, hsel)) == NULL)
return (0);
while ( (hsel = gethmenu(mn, hmenu, hsel)) != 0) {
vsel = 1;
while ( (vsel = getvmn(mn, hmenu, &hsel, vsel)) !=0) {
if(! h)
vpushscreen();
Wdelete(hmenu);
if(! h)
vpopscreen();
(*(mn+hsel-1)->func [vsel-1])(hsel, vsel);
if ((hmenu = openmenu(mn, hsel)) == NULL)
return (0);
}
}
Wdelete(hmenu);
vpopcur();
return (1);
}
/* ------------------------------------------------------------------------ */
/* open a horizontal menu */
/* ------------------------------------------------------------------------ */
static WINDOW *openmenu(MENU *mn, int hsel)
{
WINDOW *wnd;
vhidecur();
if ( (wnd = Westablish(0, 0, 3, w)) == NULL)
return (NULL);
Wsettitle(wnd, ms.title,ms.tjust);
WBORDER = MWIN_BORDER;
WTITLEC = MWIN_TITLEC;
WACCENT = MWIN_ACCENT;
WFACE = MWIN_FACE;
Wsetborder(wnd, ms.border);
Wshow(wnd);
putitems(wnd,mn);
light(mn, wnd, hsel, 1);
return wnd;
}
/* ------------------------------------------------------------------------ */
/* get a horizontal selection */
/* ------------------------------------------------------------------------ */
static int gethmenu(MENU *mn, WINDOW *hmenu, int hsel)
{
int c;
light(mn, hmenu, hsel, 1);
while (1) {
if (kkeyhit()) {
switch (c = kgetch()) {
case RIGHT:
case LEFT : hsel = haccent(mn, hmenu, hsel, c);
break;
case ESC : return 0;
case ENTER: return hsel;
default: break;
}
}
} /* while */
}
/* ------------------------------------------------------------------------ */
/* pop down a vertical menu */
/* ------------------------------------------------------------------------ */
static int getvmn(MENU *mn,WINDOW *hmenu,int *hsel,int vsel)
{
WINDOW *wnd;
int ht, wd,x;
char **mp;
while (1) {
dimension((mn+*hsel-1)->mselcs, &ht, &wd);
x = getvertpos((mn+*hsel-1)->mselcs,*hsel-1);
wnd = Westablish(x, 2, ht, wd);
WBORDER = MWIN_BORDER;
WACCENT = MWIN_ACCENT;
WFACE = MWIN_FACE;
Wsetborder(wnd, ms.border+4);
Wshow(wnd);
mp = (mn+*hsel-1)->mselcs;
while(*mp)
Wprintf(wnd, "\n%s", *mp++);
vsel = Wgetsel(wnd, vsel, "");
Wdelete(wnd);
if (vsel == RIGHT || vsel == LEFT) {
*hsel = haccent(mn, hmenu, *hsel, vsel);
vsel = 1;
}
else
return vsel;
}
}
/* ------------------------------------------------------------------------ */
/* set colours */
/* ------------------------------------------------------------------------ */
void Msetcolour(int area,int bg,int fg,int inten)
{
if (ISMONO()) {
if (bg != WHITE && bg != BLACK)
return;
if (fg != WHITE && fg != BLACK)
return;
}
if (area == WIN_ALL)
while (area)
MCOLOUR [--area] = CLR(bg, fg, inten);
else
MCOLOUR [area] = CLR(bg, fg, inten);
}
/* ------------------------------------------------------------------------ */
/* set the window's border */
/* ------------------------------------------------------------------------ */
void Msetborder(int btype)
{
ms.border = btype;
}
/* ------------------------------------------------------------------------ */
/* set the window's border */
/* ------------------------------------------------------------------------ */
void Msetspace(int sp, int a)
{
if ((a) & SPC_LEFT)
ms.lspace = sp;
if ((a) & SPC_RIGHT)
ms.rspace = sp;
if ((a) & SPC_BETWEEN)
ms.hspace = sp;
}
/* ------------------------------------------------------------------------ */
/* set title */
/* ------------------------------------------------------------------------ */
void Msettitle(char *title, int just)
{
ms.title = title;
ms.tjust = just;
}
/* ------------------------------------------------------------------------ */
/* set title */
/* ------------------------------------------------------------------------ */
void Msetfullwidth(int f)
{
if (f)
ms.hfull = 1;
else
ms.hfull = 0;
}
/* ------------------------------------------------------------------------ */
/* display all the items on the vertical bar */
/* ------------------------------------------------------------------------ */
static void putitems(WINDOW *wnd, MENU *mn)
{
int l;
hc = 0;
for (l = 0 ; l < ms.lspace ; l++)
Wputch(wnd,' ');
while (mn->mname) {
Wprintf(wnd, "%s", mn->mname);
for (l = 0 ; l < ms.hspace ; l++)
Wputch(wnd,' ');
mn++;
hc++;
}
}
/* ------------------------------------------------------------------------ */
/* manage the horizontal menu selection accent */
/* ------------------------------------------------------------------------ */
static int haccent(MENU *mn,WINDOW *hmenu,int hsel,int sel)
{
switch (sel) {
case RIGHT : light(mn, hmenu, hsel, 0);
if ((mn+hsel)->mname)
hsel++;
else
hsel = 1;
light(mn, hmenu, hsel, 1);
break;
case LEFT : light(mn, hmenu, hsel, 0);
if (hsel == 1)
while ((mn+hsel)->mname)
hsel++;
else
--hsel;
light(mn, hmenu, hsel, 1);
break;
default : break;
}
return hsel;
}
/* ------------------------------------------------------------------------ */
/* compute a menu's height & width */
/* ------------------------------------------------------------------------ */
static void dimension(char *sl[], int *ht, int *wd)
{
*ht = *wd = 0;
while (sl [*ht]) {
*wd = max(*wd, strlen(sl [*ht]));
(*ht)++;
}
*ht += 2;
*wd += 2;
}
/* ------------------------------------------------------------------------ */
/* accent a horizontal menu selection */
/* ------------------------------------------------------------------------ */
static void light(MENU *mn, WINDOW *hmenu, int hsel, int d)
{
if (d)
Wrevvideo(hmenu);
Wcursor(hmenu, irec[hsel-1].x, 0);
Wprintf(hmenu, (mn+hsel-1)->mname);
Wresetvideo(hmenu);
}
/* ------------------------------------------------------------------------ */
/* compute the window width required for the horizontal menu bar */
/* ------------------------------------------------------------------------ */
static int getwidth(MENU *mn)
{
int c = 1,wd = 0;
const MENU *mptr = mn;
irec[0].x = ms.lspace;
wd = ms.lspace;
while ((mptr)->mname) {
wd += strlen(mptr->mname) + ms.hspace;
irec[c].x = wd;
irec[(c++)-1].xx = strlen((mptr++)->mname);
}
wd -= ms.hspace;
return (wd+ms.rspace+2);
}
/* ------------------------------------------------------------------------ */
/* compute the window position required for the vertical menu */
/* ------------------------------------------------------------------------ */
static int getvertpos(char **sl, int h)
{
int x,l = 0;
while (*sl) {
l = max(l,strlen(*sl));
sl++;
}
if (h > (hc /2))
x = -3;
else
x = 2;
return ( (irec[h].x+l < w) ? irec[h].x : (w-l)) +x;
}